home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / msysjour / vol06 / 01 / kermit / wnkerm.w < prev    next >
Text File  |  1990-12-31  |  8KB  |  300 lines

  1. /*
  2.  * WNKERM.W
  3.  * Protocol module for Windows Kermit
  4.  * 
  5.  * Copyright (c) 1990 by
  6.  * William S. Hall
  7.  * 3665 Benton Street  #66
  8.  * Santa Clara, CA 95051
  9.  *
  10.  * This module must be preprocessed by wart
  11.  */
  12.  
  13. #define NOCOMM
  14. #define NOKANJI
  15. #define NOSOUND
  16. #define NOATOM
  17. #include <windows.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "wnkerm.h"
  21.  
  22. /* The state machine returns 0 to show completion or 1 if more input
  23.  * is expected.  Currently, these return values are not used.
  24.  */
  25. #define RESUME return(0)
  26. #define CONTINUE return(1)
  27.  
  28. /* local function prototypes */
  29. static int near input(void);
  30.  
  31. /* protocol states */
  32. %states rsinit rsfile rsdata
  33. %states ssinit ssfile ssdata sseof sseot
  34.  
  35. /* Protocol description.
  36.  */
  37. %%
  38.  
  39. /* Begin file send
  40.  */
  41. s {        
  42.     krm_tinit();            /* initialize */
  43.     Kermit.start = 'w';            /* switch to wait */
  44. }
  45.  
  46. /* Wait to send first packet
  47.  */
  48. w {
  49.     if (Kermit.delay) {            /* timer will reset this parameter */
  50.     Kermit.start = 'w';        /* wait to send first packet */
  51.         CONTINUE;
  52.     } else {
  53.         if (krm_sinit() < 0) {            /* transmit sendinit packet */
  54.             krm_err(IDS_KRM_SENDINIT_ERROR);    /* error; inform remote */
  55.             RESUME;                /* quit */
  56.         }    
  57.     krmFlushQue();        /* flush any pending input in local buffer */
  58.         BEGIN ssinit;        /* prepare to open file and send file name */
  59.     }    
  60. }
  61.  
  62. /* Begin receive file
  63.  */
  64. v {
  65.     krm_tinit();            /* initialize */
  66.     BEGIN rsinit;            /* prepare to receive init packet */
  67. }
  68.  
  69. /* got ACK of sendinit packet
  70.  */
  71. <ssinit>Y {
  72.     krm_spar(krm_rcvpkt.data, krm_rcvpkt.len);    /* set init data */
  73.     Kermit.bctu = Kermit.bctr;            /* select block check type */
  74.     Kermit.pFile = krm_getnextfile(TRUE);    /* get file to send */
  75.     if (krm_sfile() < 0) {            /* send file name packet */
  76.         krm_err(IDS_KRM_SENDFILENAME_ERROR);    /* error; inform remote */
  77.         RESUME;                    /* quit */
  78.     }
  79.     BEGIN ssfile;               /* prepare to send first data packet */
  80. }
  81.  
  82. /* Got ACK of file name packet
  83.  */
  84. <ssfile>Y {
  85.     int x;
  86.     krm_savename();            /* post the remote's name for file */
  87.     if ((x = krm_sdata()) == 0) {    /* no data in file */
  88.         if (krm_seof("") < 0) {        /* send end of file */
  89.            krm_err(IDS_KRM_SENDEOF_ERROR);   /* error; inform remote */
  90.            RESUME;            /* quit */
  91.         }
  92.         BEGIN sseof;
  93.     }
  94.     else if (x < 0) {            /* error in sending file */
  95.         krm_rclose(FALSE);        /* close the file */
  96.         krm_err(IDS_KRM_SENDDATA_ERROR); /* post error to remote and quit */
  97.         RESUME;
  98.     }
  99.     else
  100.     BEGIN ssdata;            /* prepare to receive data */
  101. }
  102.  
  103. /* Got ACK to data packet
  104.  */
  105. <ssdata>Y {                
  106.     krm_checkcnx();            /* check if transaction cancelled */
  107.     if (Kermit.abort) {
  108.     if (Kermit.abort == KRM_FILEABORT)  /* cancel file send */
  109.         Kermit.abort = 0;
  110.     if (krm_seof("D") < 0) {        /* tell remote about cancellation */
  111.        krm_err(IDS_KRM_SENDEOF_ERROR);  /* error; inform remote */
  112.        RESUME;                /* quit */
  113.     }
  114.         BEGIN sseof;            /* prepare to send end of file */
  115.     }
  116.     else {
  117.         int x;
  118.     if ((x = krm_sdata()) == 0) {        /* no more data */
  119.         if (krm_seof("") < 0) {        /* send end of file */
  120.            krm_err(IDS_KRM_SENDEOF_ERROR);  /* error; inform remote */
  121.            RESUME;                /* quit */
  122.         }
  123.             BEGIN sseof;        /* prepare to send end of file */
  124.         }
  125.     else if (x < 0) {            /* error */
  126.         krm_rclose(FALSE);            /* close the file */
  127.         krm_err(IDS_KRM_SENDDATA_ERROR);    /* inform remote */
  128.         RESUME;                /* quit */
  129.         }
  130.     }
  131. }
  132.  
  133. /* Got ACK to end of file packet
  134.  */
  135. <sseof>Y {
  136.     if (Kermit.pFile = krm_getnextfile(FALSE)) {  /* any more files? */
  137.         if (krm_sfile() < 0) {              /* send next file name */
  138.             krm_err(IDS_KRM_SENDFILENAME_ERROR);  /* error, inform remote */
  139.             RESUME;                  /* quit */
  140.         }
  141.         BEGIN ssfile;                /* prepare for next file */
  142.     }    
  143.     else {                    /* no more files to send */
  144.     if (krm_seot() < 0) {            /* send break */
  145.         krm_err(IDS_KRM_SENDEOT_ERROR);    /* error, inform remote */
  146.         RESUME;                /* quit */
  147.     }
  148.     BEGIN sseot;                /* prepare to exit file send */
  149.     }
  150. }
  151.  
  152. /* Got ACK to end of transmission packet
  153.  */
  154. <sseot>Y {
  155.     krm_tend(IDS_KRM_TRANSACTION_DONE);        /* clean up */
  156.     RESUME;                    /* quit */
  157. }
  158.  
  159. /* Got sendinit packet
  160.  */
  161. <rsinit>S {
  162.     BYTE data[KRM_MAXDATALEN + 1];
  163.     krm_spar(krm_rcvpkt.data, krm_rcvpkt.len);    /* read send-init data */
  164.     krm_ack(krm_rpar(data), data);        /* return init data in ACK */
  165.     Kermit.bctu = Kermit.bctr;            /* set block check type */
  166.     BEGIN rsfile;                    /* prepare for file name */
  167. }
  168.  
  169. /* Got file name packet
  170.  */
  171. <rsfile>F {
  172.     if (krm_rcvfil()) {                /* try to open file */
  173.     char buf[KRM_MAXDATALEN + 1];            
  174.     int inlen, outlen;
  175.     inlen = strlen(Kermit.pFile);        /* return our name to remote */
  176.     outlen = krm_encode(buf, Kermit.pFile, sizeof(buf) - 1, &inlen);
  177.         krm_ack(outlen, buf);            /* send the name in ACK */
  178.         BEGIN rsdata;                /* prepare to receive data */
  179.     }
  180.     else {
  181.     krm_err(IDS_KRM_FILE_OPEN_ERROR);    /* error, inform remote */
  182.     RESUME;                    /* quit */
  183.     }
  184. }
  185.  
  186. /* Got data packet
  187.  */
  188. <rsdata>D {
  189.     if (krm_rcvdata()) {
  190.     switch(Kermit.abort) {            /* see if abort flag is on */
  191.         case KRM_BATCHABORT:
  192.         krm_ack(1, "Z");        /* cancel remaining files */
  193.         Kermit.abort = 0;
  194.         break;
  195.         case KRM_FILEABORT:
  196.         krm_ack(1, "X");        /* cancel current file */
  197.         Kermit.abort = 0;
  198.         break;
  199.         default:
  200.         krm_ack(0, "");                /* continue */
  201.     }
  202.     }
  203.     else {
  204.     krm_rclose(TRUE);            /* error in storing data */
  205.     krm_err(IDS_KRM_FILE_WRITE_ERROR);    /* inform host */
  206.     RESUME;                    /* quit */
  207.     }
  208. }
  209.  
  210. /* Got end of file packet
  211.  */
  212. <rsdata>Z {        /* see if remote wants us to delete file */
  213.     if (krm_rclose(krm_rcvpkt.len && 
  214.     (krm_rcvpkt.data[0] == 'D') ? TRUE : FALSE)) {
  215.         krm_ack(0, "");                /* acknowledge */
  216.         BEGIN rsfile;                /* prepare for next file */
  217.     }
  218.     else {
  219.     krm_err(IDS_KRM_FILE_CLOSE_ERROR);    /* error; inform remote */
  220.     RESUME;                    /* quit */
  221.     }
  222. }
  223.  
  224. /* Got end of transmission packet
  225.  */
  226. <rsfile>B {
  227.     krm_ack(0, "");            /* acknowledge */
  228.     krm_tend(IDS_KRM_TRANSACTION_DONE);    /* clean up */
  229.     RESUME;                /* quit */
  230. }
  231.  
  232. /* Packet is incomplete; return.
  233.  */
  234. $ {
  235.     CONTINUE;            /* continue until packet is filled */
  236. }
  237.  
  238. /* Got error packet
  239.  */
  240. E {
  241.     krm_rclose(TRUE);        /* close any open files */
  242.     krm_tend(KRM_ERROR_PACKET);    /* clean up */
  243.     RESUME;            /* quit */
  244. }
  245.  
  246. /* Unrecognized packet
  247.  */
  248. . {
  249.     krm_rclose(TRUE);            /* close any open files */
  250.     krm_err(IDS_KRM_UNKNOWN_PACKET);    /* post error to remote */
  251.     RESUME;                /* quit */
  252. }
  253.  
  254. %%
  255.  
  256. /* input
  257.  *
  258.  * provide packet type to state machine
  259.  */
  260. static int near input()
  261. {
  262.  
  263.     register int type;
  264.  
  265.     if (Kermit.start) {
  266.     type = Kermit.start;
  267.     Kermit.start = 0;
  268.     }
  269.     else {
  270.     type = krm_rpack();        /* read input */
  271.     if ((type != '$') && (type != 'E'))  {
  272.       /* packet is complete but is not an error packet */
  273.         if ((Kermit.seq != krm_rcvpkt.seq) || strchr("NQT", type)) {
  274.           /* something is wrong with packet */
  275.             if (Kermit.retries >= KermParams.RetryLimit) {
  276.           /* pretend we have an error packet */
  277.             krmCreatePseudoPacket('E', PS_DONE, IDS_KRM_TOOMANYRETRIES);
  278.             type = 'E';
  279.             }
  280.             else if ((type == 'N') && 
  281.               (krm_rcvpkt.seq == ((Kermit.seq + 1) & 63))) {
  282.           /* this is OK since NAK for next packet is ACK for previous */
  283.             type = 'Y';
  284.             Kermit.retries = 0;
  285.             }
  286.             else {
  287.           /* resend previous packet and try again */
  288.             Kermit.retries += 1;
  289.             Kermit.totalretries += 1;
  290.             krm_resend();
  291.             type = '$';
  292.             }
  293.         }
  294.         else    /* packet is OK; reset retry count */
  295.             Kermit.retries = 0;
  296.     }
  297.     }
  298.     return (type);
  299. }
  300.